#ifndef HASH_SELECT_HPP
#define HASH_SELECT_HPP

#include <vector>
#include <string>
#include <functional>
#include <mutex>

#include "./LoadBalancePolicyIface.h"

namespace LoadBalance
{
    template <typename T>
    class HashSelect : public LoadBalancePolicyIface<T>
    {
    public:
        HashSelect() = delete;
    };

    // TODO: 优化对外接口操作不只是基于std::string
    template <>
    class HashSelect<std::string> : public LoadBalancePolicyIface<std::string>
    {
    public:
        explicit HashSelect(const std::vector<std::string> &nodes, std::function<size_t(const std::string &)> hashFunc = std::hash<std::string>())
            : nodes_(nodes), hashFunc_(hashFunc)
        {
        }

        std::string getNode(const std::string &key)
        {
            std::lock_guard<std::mutex> lock(this->mtx_);

            if (this->nodes_.empty()) // 注意错误处理
            {
                return "";
            }

            size_t keyHash = this->hashFunc_(key);
            size_t idx = keyHash % this->nodes_.size(); // 注意循环回绕
            return this->nodes_[idx];
        }

        // TODO: 这里没用到接口，可以优化接口更通用
        std::string getNext() override
        {
            return "";
        }

    private:
        std::vector<std::string> nodes_;
        std::function<size_t(const std::string &)> hashFunc_;

        std::mutex mtx_; // 注意线程安全
    };
} // namespace LoadBalance

#endif // HASH_SELECT_HPP